﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Configuration;
using System.Configuration;
using System.Xml;
using System.Data;

namespace Twi.COMMON.Core
{
    /*
     * CopyRight:©2012 Twilight软件开发工作室版权所有
     * Author:xuzhihong
     * Create Date: 2012-07-24
     * Description: 获取WebConfig中的信息
     */
    public class TwiConfigHelper
    {
        /// <summary>
        /// 获取WebConfig中的connectionStrings字符串
        /// </summary>
        /// <param name="name">配置文件中name的值</param>
        /// <param name="path">配置文件的虚拟路径。如果为 null，则打开根 Web.config 文件.如："/Areas/BIM/Views"</param>
        /// <returns>应配置文件中connectionString的值</returns>
        /// <example>
        /// 例如配置文件的内容为：
        /// 	<connectionStrings>
        /// 	    <add name="BIMConnectionString" connectionString="Data Source=.;Initial Catalog=GS.AHB;User Id=sa;Password=123456;" providerName="System.Data.SqlClient"/>
        /// 	</connectionStrings>
        /// 则该方法的参数为name的值
        /// 返回值为对应的connectionString的值
        /// </example>
        /// <remarks>如果配置了path,但是在path之中的Web.config文件没找到，则会自动到根目录中的Web.config再去查找一次。</remarks>
        public static string GetConnectionString(string name,string path=null)
        {
            string connStr = null;
            if (!string.IsNullOrEmpty(path))
            {
                Configuration config = WebConfigurationManager.OpenWebConfiguration(path);
                if (config.ConnectionStrings.ConnectionStrings[name] != null)
                {
                    connStr = config.ConnectionStrings.ConnectionStrings[name].ConnectionString;
                }                
            }
            if(string.IsNullOrEmpty(connStr))
            {
                if (WebConfigurationManager.ConnectionStrings[name] != null)
                {
                    connStr = WebConfigurationManager.ConnectionStrings[name].ConnectionString;
                }
            }
            return connStr;
        }
        /// <summary>
        /// 获取WebConfig中的第一个connectionStrings字符串
        /// </summary>
        /// <returns></returns>
        public static string GetFirstOrDefaultConnectionString()
        {
            if (WebConfigurationManager.ConnectionStrings.Count > 0)
            {
                return WebConfigurationManager.ConnectionStrings[0].ConnectionString;
            }
            return null;
        }

        /// <summary>
        /// 获取WebConfig中连接数据库字符串中的providerName值
        /// </summary>
        /// <param name="name">配置文件中name的值</param>
        /// <param name="path">配置文件的虚拟路径。如果为 null，则打开根 Web.config 文件.如："/Areas/BIM/Views"</param>
        /// <returns>providerName值</returns>
        public static string GetProviderName(string name,string path=null)
        {
            string providerName = null;
            if (!string.IsNullOrEmpty(path))
            {
                Configuration config = WebConfigurationManager.OpenWebConfiguration(path);
                if (config.ConnectionStrings.ConnectionStrings[name] != null)
                {
                    providerName = config.ConnectionStrings.ConnectionStrings[name].ProviderName;
                }  
            }
            if(string.IsNullOrEmpty(providerName))
            {
                if (WebConfigurationManager.ConnectionStrings[name] != null)
                {
                    providerName = WebConfigurationManager.ConnectionStrings[name].ProviderName;
                }          
            }
            return providerName;
        }

        /// <summary>
        /// 获取WebConfig中第一个连接数据库字符串中的providerName值
        /// </summary>
        /// <returns></returns>
        public static string GetFirstOrDefaultProviderName()
        {
            if (WebConfigurationManager.ConnectionStrings.Count > 0)
            {
                return WebConfigurationManager.ConnectionStrings[0].ProviderName;
            }
            return null;
        }

        /// <summary>
        /// 获取WebConfig中的appSettings的对应键的值
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="path">配置文件的虚拟路径。如果为 null，则打开根 Web.config 文件.如："/Areas/BIM/Views"</param>
        /// <returns>value</returns>
        /// <example>
        /// 例如：
        ///     <appSettings>
        ///         <add key="FfmpegUrl" value=""/><!--fffmpeg路径-->
        ///         <add key="CVMS_DBConnectionString" value="Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.70) (PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=CVMS)));User Id=system;Password=123456;Integrated Security=no"/>
        ///     </appSettings>
        /// </example>
        public static string GetAppSettingValue(string key, string path = null)
        {
            string strValue = null;
            if (string.IsNullOrEmpty(path))
            {
                strValue = ConfigurationManager.AppSettings[key];
            }
            else
            {
                Configuration config = WebConfigurationManager.OpenWebConfiguration(path);
                if (config.AppSettings.Settings[key] != null)
                {
                    strValue = config.AppSettings.Settings[key].Value;
                }                
            }
            return strValue;
        } 
    }


    /// <summary>
    /// Twi数据库链接统一配置
    /// </summary>
    public class TwiDBConnectionHelper
    {
        private string _dbConfigFullPath = TwiPathHelper.MapPath("~/Config/TwiDBConnection.config");
        public TwiDBConnectionHelper() { }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="dbConfigPath">配置文件完整路径</param>
        public TwiDBConnectionHelper(string dbConfigFullPath)
        {
            _dbConfigFullPath = dbConfigFullPath;
        }

        /// <summary>
        /// 获取所有连接
        /// </summary>
        /// <returns>
        /// DataTable有两列,数据格式如下：
        /// ----------------------------
        /// Value     Text
        /// ----------------------------
        /// Default   默认连接(Default)
        /// BIM       基础信息(BIM)
        /// ----------------------------
        /// </returns>
        public DataTable GetAll()
        {
            ExamineConfigFile();
            DataTable dt = new DataTable();
            dt.Columns.Add("Value");
            dt.Columns.Add("Text");
            XmlElement root = GetRootElement();
            XmlNodeList items = root.SelectNodes("//item");
            foreach (XmlNode node in items)
            {
                DataRow row = dt.NewRow();
                if (node.Attributes["code"] == null)
                {
                    throw new Exception("检测到，TwiDBConnection存在未配置code属性的连接!");
                }
                else if (node.Attributes["cnName"] == null)
                {
                    throw new Exception("检测到，TwiDBConnection存在未配置cnName属性的连接!");
                }
                else
                {
                    row["Value"] = node.Attributes["code"].Value;
                    row["Text"] = string.Format("{0}({1})", node.Attributes["cnName"].Value, node.Attributes["code"].Value);
                }
                dt.Rows.Add(row);
            }            
            return dt;
        }

        /// <summary>
        /// 根据单个属性查找其他属性的值
        /// </summary>
        /// <param name="attributeName"></param>
        /// <param name="attributeValue"></param>
        /// <param name="findAttributeName"></param>
        /// <returns></returns>
        public string GetFirstOrDefaultByAttribute(string attributeName, string attributeValue, string findAttributeName)
        {
            bool existFile = TwiPathHelper.ExistFile(_dbConfigFullPath);
            string returnValue = null;
            if (existFile)
            {
                XmlElement root = GetRootElement();
                string xPath = string.Format("//item[@{0}='{1}']",attributeName,attributeValue);
                XmlNode node = root.SelectSingleNode(xPath);
                if (node != null)
                {
                    returnValue = node.Attributes[findAttributeName].Value;
                }
            }
            return returnValue;
        }

        /// <summary>
        /// 根据配置的connectionStrings.name属性值获取连接字符【ConnectionString属性值】
        /// 如果连接字符串加密了，则会自动解密
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public string GetConnectionStringByName(string name)
        {
            bool existFile = TwiPathHelper.ExistFile(_dbConfigFullPath);
            
            //为了兼容之前的  TwiDBConnection.xml 能够读取
            existFile = existFile ? existFile : TwiPathHelper.ExistFile(_dbConfigFullPath.Replace("TwiDBConnection.config", "TwiDBConnection.xml"));
            
            string returnValue = null;
            if (existFile)
            {
                XmlElement root = GetRootElement();
                string xPath = string.Format("//item[@{0}='{1}']", "name", name);
                XmlNode node = root.SelectSingleNode(xPath);
                if (node != null)
                {
                    returnValue = node.Attributes["connectionString"].Value;
                    if (node.Attributes["encryption"] !=null &&""+node.Attributes["encryption"].Value.ToLower() == "true") //需要解密
                    {
                        //returnValue = EncryptionAlgorithm.Base64Decode(returnValue);
                        returnValue = EncryptionAlgorithm.Base64CustomerDecode(returnValue);
                    }
                }
            }
            return returnValue;
        }

        /// <summary>
        /// 检测配置文件是否存在，注意：这里不存在会自动抛出异常
        /// </summary>
        private void ExamineConfigFile()
        {
            TwiPathHelper.ExistFile(_dbConfigFullPath, true, "Twi数据库连接统一配置文件不存在！");
        }

        /// <summary>
        /// 获取配置文件的根节点
        /// </summary>
        /// <returns></returns>
        private XmlElement GetRootElement()
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(_dbConfigFullPath);
            XmlElement root = xmlDoc.DocumentElement;
            return root;
        }

        private static TwiDBConnectionHelper _instance = null;
        /// <summary>
        /// 获取实例
        /// </summary>
        /// <returns></returns>
        public static TwiDBConnectionHelper GetInstance()
        {
            if (_instance == null)
            {
                _instance = new TwiDBConnectionHelper();
            }
            return _instance;
        }
    }
}
